import copy
import datetime
import sys
import threading
import time
import traceback

import matplotlib
import pandas as pd

from PyQt5.QtCore import Qt, QDateTime
from matplotlib import pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.dates import AutoDateLocator, DateFormatter
from pandas import Timestamp

from StressAna.Lib.DBProc import SQLiteDBProc
from StressAna.Lib.Model import LabelsInit, Globalvariables
from StressAna.Lib.Utils import DateTimeUtil
from StressAna.UI.UI_Main import *

from StressAna.UI.UI_DataSyncTip import *

# warnings.filterwarnings('ignore')
matplotlib.use("Qt5Agg")
plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]  # 设置默认字体
plt.rcParams["axes.unicode_minus"] = False  # 坐标轴正确显示正负号

'''
数据补数（取前一个值）
'''


def ana(data):
    for i, value in enumerate(data):
        if i > 0 and data[i] == 0:
            data[i] = data[i - 1]


'''
画布初始化
'''


class Figure_Canvas(FigureCanvas):
    def __init__(self, parent=None, width=12, height=8, dpi=100):
        self.fig = plt.Figure(figsize=(width, height), dpi=dpi, tight_layout=True)
        FigureCanvas.__init__(self, self.fig)  # 初始化父类
        self.setParent(parent)
        self.axes = self.fig.add_subplot(111)

    def drawFig(self, data_list=None, data_list2=None, labels=None, title='对比分析'):
        if data_list is None:
            data_list = []
        if data_list2 is None:
            data_list2 = []
        if labels is None:
            labels = []

        data_legend = []
        for idata in data_list:
            line = self.axes.plot(idata[0], idata[1])
            data_legend.append(line[0])

        if data_list2:
            self.ax2 = self.axes.twinx()
            for idata in data_list2:
                line = self.ax2.plot(idata[0], idata[1], alpha=0.8, linestyle='--')
                data_legend.append(line[0])
            self.ax2.set_ylabel("摄氏度/℃")

        self.axes.set_title(title, pad=25)
        self.axes.set_xlabel("时间")
        self.axes.set_ylabel("Mpa")

        locator = AutoDateLocator()
        date_fmt = DateFormatter("%Y-%m-%d %H:%M:%S")
        self.axes.xaxis.set_major_locator(locator)
        self.axes.xaxis.set_major_formatter(date_fmt)
        self.axes.tick_params(direction='in', length=6, width=2, labelsize=8)
        self.axes.xaxis.set_tick_params(labelrotation=45)
        self.axes.legend(data_legend, labels, loc=9, bbox_to_anchor=(0.5, -0.25), shadow=True, fancybox=True, ncol=4)


'''
数据对比类
'''


class StressSqlite3(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.init()

    def init(self):
        self.DF_ALL = pd.DataFrame(columns=['sID', 'time', 'ch1', 'ch2'])
        self.conn = SQLiteDBProc.SQLiteAPI(Globalvariables.DB_PATH)

        self.FILTER_CONS = []
        self.sid_list = []
        self.sync_tip_dialog = None
        self.DF_FILTER = pd.DataFrame(columns=['sID', 'time', 'chn'])

        LabelsInit.sIDAttrInit()
        self.load_tddata_slot()

        for i, dfi in Globalvariables.LABELS_DICT.groupby('length'):
            self.cb_CD.addItem(i)
        for i, dfi in Globalvariables.LABELS_DICT.groupby('wallThick'):
            self.cb_BH.addItem(i)
        for i, dfi in Globalvariables.LABELS_DICT.groupby('holeDepth'):
            self.cb_KS.addItem(i)
        for i, dfi in Globalvariables.LABELS_DICT.groupby('initialPress'):
            self.cb_CSY.addItem(i)

        now_day = time.strftime("%Y-%m-%d", time.localtime())
        self.dateEdit.setDateTime(QDateTime.fromString(f'{now_day}', "yyyy-MM-dd"))
        self.dateEdit_2.setDateTime(QDateTime.fromString(f'{now_day}', "yyyy-MM-dd"))
        self.DTEdit_start.setDateTime(QDateTime.fromString(f'{now_day} 00:00:00', "yyyy-MM-dd HH:mm:ss"))
        self.DTEdit_end.setDateTime(QDateTime.fromString(f'{now_day} 00:00:00', "yyyy-MM-dd HH:mm:ss"))
        self.pb_draw_max.hide()

    '''
    导入泰德数据
    '''

    def load_tddata_slot(self):
        result = self.conn.select('device_info', 'code,channel')
        for row in result:
            sid = f"{row[0]}-{row[1]}"
            if sid not in self.sid_list:
                self.sid_list.append(sid)
                newitem = QtWidgets.QListWidgetItem(f"{sid}:{LabelsInit.get_sIDAttr(sid)}")
                newitem.setCheckState(0)
                self.listWidget.addItem(newitem)

    def load_skdata_slot(self):
        pass

    def load_mondata_slot(self):
        pass

    '''
    绘制波形
    '''

    def draw_slot(self):
        start_date = self.dateEdit.dateTime().date().toString("yyyy-MM-dd")
        end_date = self.dateEdit_2.dateTime().date().toString("yyyy-MM-dd")
        start_datetime = self.dateEdit.dateTime().date().toString("yyyy-MM-dd 00:00:00")
        end_datetime = self.dateEdit_2.dateTime().date().toString("yyyy-MM-dd 23:59:59")

        if start_datetime >= end_datetime:
            print('开始时间不能大于结束时间！')
            return

        sIDs = []
        for i in range(self.listWidget.count()):
            if self.listWidget.item(i).checkState():
                sIDs.append(self.listWidget.item(i).text())
        for i in range(self.listWidget_2.count()):
            if self.listWidget_2.item(i).checkState():
                sIDs.append(f"{self.listWidget_2.item(i).text()}:(思科赛德数据)")

        data_list = []
        data_list2 = []
        curDataList = []  # 开始压力和结束压力
        start_data = 0  # 找到开始的压力 默认0
        end_data = 0  # 找到结束的压力 默认0

        date_list = DateTimeUtil.get_date_str_list_by_date_range(start_date, end_date, '%Y-%m-%d')
        _date = ','.join([f"'{x}'" for x in date_list])
        for item in sIDs:
            iName = item.split(':')[0]
            sID, chnNum = iName.split('-')
            sql = f"SELECT d.code, d.channel, s.date_time, s.value FROM stress_data s inner join device_info d on s.device_id=d.id WHERE d.code='{sID}' and d.channel='{chnNum}' and s.date in ({_date})"
            result = self.conn.select_by_sql(sql)
            srcX = []
            srcY = []
            dstX = []
            dstY = []
            CtrX = []
            CtrY = []
            for row in result:
                row_date_time_list = row[2].split(',')
                row_value_list = row[3].split(',')
                srcX.extend(row_date_time_list)
                srcY.extend(row_value_list)
            for i, date_time in enumerate(srcX):
                if start_datetime <= date_time <= end_datetime:
                    dstX.append(date_time)
                    dstY.append(srcY[i])
            X = [datetime.datetime.strptime(x, "%Y-%m-%d %H:%M:%S") for x in dstX]
            Y = [float(x) for x in dstY]

            # 补数
            if self.cb_comple.checkState():
                ana(Y)
            # 查找开始和结束压力
            for i in Y:
                if str(i) != 'nan':
                    start_data = i
                    break
            for i in Y[::-1]:
                if str(i) != 'nan':
                    end_data = i
                    break
            # 不显示-9999的数据
            for i, value in enumerate(Y):
                if value != -9999:
                    CtrX.append(X[i])
                    CtrY.append(value)
            data_list.append((CtrX, CtrY))
            curDataList.append((iName, start_data, end_data))

        if not data_list:
            print('没有找到数据！')
            return
        self.setViewTail(data_list=data_list, data_list2=data_list2, labels=sIDs)

        self.DF_FILTER = pd.DataFrame(columns=['sID', 'time', 'chn'])
        for i, item in enumerate(sIDs):
            iName = item.split(':')[0]
            sid_data = data_list[i]
            dataLen = len(sid_data[0])
            sid_list = [iName] * dataLen
            df = pd.DataFrame(data=[sid_list, sid_data[0], sid_data[1]])
            df = df.T
            df.columns = ['sID', 'time', 'chn']
            self.DF_FILTER = self.DF_FILTER._append(df)

        # 显示当前波形开始压力值和结束压力值
        self.textBrowser_2.clear()
        self.textBrowser_3.clear()
        self.textBrowser_4.clear()
        text_sids = []
        text_values1 = []
        text_values2 = []
        for row, row_values in enumerate(curDataList):
            text_sids.append(f'{row_values[0]}')
            text_values1.append(f'{row_values[1]}')
            text_values2.append(f'{row_values[2]}')
        self.textBrowser_2.setText('\n'.join(text_sids))
        self.textBrowser_3.setText('\n'.join(text_values1))
        self.textBrowser_4.setText('\n'.join(text_values2))
        self.cB_sidFilter.clear()
        for sid in sIDs:
            self.cB_sidFilter.addItem(sid)
        self.FILTER_CONS = []
        self.pb_draw_max.show()

    def fliter_draw_slot(self):
        start_time_str = self.dateEdit.dateTime().date().toString("yyyy-MM-dd 00:00:00")
        end_time_str = self.dateEdit_2.dateTime().date().toString("yyyy-MM-dd 23:59:59")

        if start_time_str >= end_time_str:
            print('开始时间不能大于结束时间！')
            return

        filter_start_time_str = self.DTEdit_start.dateTime().toPyDateTime()
        filter_end_time_str = self.DTEdit_end.dateTime().toPyDateTime()
        filter_sid_str = self.cB_sidFilter.currentText()
        filter_sid = filter_sid_str.split(':')[0]
        self.FILTER_CONS.append((filter_start_time_str, filter_end_time_str, filter_sid))
        if filter_start_time_str >= filter_end_time_str:
            print('开始时间不能大于结束时间！')
            return

        sIDs = []
        labels = []
        for i in range(self.listWidget.count()):
            if self.listWidget.item(i).checkState():
                sIDs.append(self.listWidget.item(i).text())
        for i in range(self.listWidget_2.count()):
            if self.listWidget_2.item(i).checkState():
                sIDs.append(f"{self.listWidget_2.item(i).text()}:(思科赛德数据)")

        data_list = []
        data_list2 = []
        curDataList = []  # 开始压力和结束压力
        start_data = 0  # 找到开始的压力 默认0
        end_data = 0  # 找到结束的压力 默认0

        for item in sIDs:
            sID = item.split(':')[0]

            _df = self.DF_FILTER[(self.DF_FILTER['sID'] == sID)]
            x = _df['time'].to_list()
            y = _df['chn'].to_list()
            if self.cb_comple.checkState():
                ana(y)
            # 不显示-9999的数据
            CtrX = []
            CtrY = []
            for i in range(len(x)):
                skip_flag = False
                if y[i] == -9999:
                    continue
                for cons in self.FILTER_CONS:
                    filter_start_time, filter_end_time, f_sid = cons
                    if f_sid == sID and (filter_start_time <= x[i] <= filter_end_time):
                        skip_flag = True
                        break
                if skip_flag:
                    continue
                CtrX.append(x[i])
                CtrY.append(y[i])
            data_list.append((CtrX, CtrY))

            for i in CtrY:
                if str(i) != 'nan':
                    start_data = i
                    break
            for i in CtrY[::-1]:
                if str(i) != 'nan':
                    end_data = i
                    break
            curDataList.append((sID, start_data, end_data))
        if not data_list:
            print('没有找到数据！')
            return

        self.setViewTail(data_list=data_list, data_list2=data_list2, labels=sIDs)

        # 显示当前波形开始压力值和结束压力值
        self.textBrowser_2.clear()
        self.textBrowser_3.clear()
        self.textBrowser_4.clear()
        text_sids = []
        text_values1 = []
        text_values2 = []
        for row, row_values in enumerate(curDataList):
            text_sids.append(f'{row_values[0]}')
            text_values1.append(f'{row_values[1]}')
            text_values2.append(f'{row_values[2]}')
        self.textBrowser_2.setText('\n'.join(text_sids))
        self.textBrowser_3.setText('\n'.join(text_values1))
        self.textBrowser_4.setText('\n'.join(text_values2))

    '''
    绘制最大值波形
    '''

    def draw_max_slot(self):
        self.drawPic.setEnabled(False)
        start_time_str = self.dateEdit.dateTime().date().toString("yyyy-MM-dd 00:00:00")
        end_time_str = self.dateEdit_2.dateTime().date().toString("yyyy-MM-dd 23:59:59")

        sIDs = []
        for i in range(self.listWidget.count()):
            if self.listWidget.item(i).checkState():
                sIDs.append(self.listWidget.item(i).text())
        for i in range(self.listWidget_2.count()):
            if self.listWidget_2.item(i).checkState():
                sIDs.append(self.listWidget_2.item(i).text())

        data_list = []
        if 'date' not in self.DF_FILTER.columns:
            self.DF_FILTER['date'] = self.DF_FILTER['time'].astype('str').apply(lambda x: x[:10])
        for item in sIDs:
            sID = item.split(':')[0]
            df_sel = self.DF_FILTER[(self.DF_FILTER['sID'] == sID)]
            x = []
            y = []
            for idate, dfi in df_sel.groupby('date'):
                x.append(Timestamp(f"{idate} 00:00:00"))
                y.append(dfi[f'chn'].max())

            # 不显示-9999的数据
            CtrX = []
            CtrY = []
            for i, value in enumerate(y):
                if value != -9999:
                    CtrX.append(x[i])
                    CtrY.append(value)
            data_list.append((CtrX, CtrY))
            # data_list.append((x, y))
        self.setViewTail(data_list=data_list, labels=sIDs)

    '''
    展示波形
    '''

    def setViewTail(self, data_list=None, data_list2=None, labels=None):
        # 图例
        labels = LabelsInit.labelsInit(labels)
        self.drawPic.setEnabled(False)

        self.fig_canvas = Figure_Canvas()  # 实例化类
        self.fig_canvas.drawFig(data_list=data_list, data_list2=data_list2, labels=labels,
                                title=self.lineEdit.text())  # 调用类方法，作图
        self.graphicscene = QtWidgets.QGraphicsScene()  # 创建一个QGraphicsScene，因为加载的图形（FigureCanvas）不能直接放到graphicview控件中，必须先放到graphicScene，然后再把graphicscene放到graphicview中
        self.graphicscene.addWidget(self.fig_canvas)  # 把图形放到QGraphicsScene中，注意：图形是作为一个QWidget放到QGraphicsScene中的
        self.graphicsView.setScene(self.graphicscene)  # 把QGraphicsScene放入QGraphicsView
        self.graphicsView.show()  # 调用show方法呈现图形

        self.drawPic.setEnabled(True)

    def draw_finish_slot(self):
        self.drawPic.setEnabled(True)

    '''
    泰德数据全选
    '''

    def selall_slot1(self):
        for i in range(self.listWidget.count()):
            if not self.listWidget.item(i).checkState():
                self.listWidget.item(i).setCheckState(2)

    '''
    思科数据全选
    '''

    def selall_slot2(self):
        for i in range(self.listWidget_2.count()):
            if not self.listWidget_2.item(i).checkState():
                self.listWidget_2.item(i).setCheckState(2)

    '''
    泰德数据取消全选
    '''

    def selnoall_slot1(self):
        for i in range(self.listWidget.count()):
            if self.listWidget.item(i).checkState():
                self.listWidget.item(i).setCheckState(0)

    '''
    思科数据取消全选
    '''

    def selnoall_slot2(self):
        for i in range(self.listWidget_2.count()):
            if self.listWidget_2.item(i).checkState():
                self.listWidget_2.item(i).setCheckState(0)

    def sel_addr_slot(self):
        CD = self.cb_CD.currentText()
        BH = self.cb_BH.currentText()
        KS = self.cb_KS.currentText()
        CSY = self.cb_CSY.currentText()
        df = copy.deepcopy(Globalvariables.LABELS_DICT)
        if CD != '全部':
            df = df[(df['length'] == CD)]
        if BH != '全部':
            df = df[(df['wallThick'] == BH)]
        if KS != '全部':
            df = df[(df['holeDepth'] == KS)]
        if CSY != '全部':
            df = df[(df['initialPress'] == CSY)]
        # df_sel = df[(df['length']==CD) & (df['wallThick']==BH) & (df['holeDepth']==KS) & (df['initialPress']==CSY)]
        sta_list = df['sta'].unique().tolist()
        self.selnoall_slot1()
        for sta in sta_list:
            for i in range(self.listWidget.count()):
                if sta in self.listWidget.item(i).text():
                    self.listWidget.item(i).setCheckState(2)

    def re_sel_slot(self):
        pass

'''
数据同步提示框
'''


class SyncTipDialog(QtWidgets.QDialog, Ui_DataSyncTip):
    def __init__(self):
        super(SyncTipDialog, self).__init__()
        self.setupUi(self)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.label.setText('绘制应力历史波形中，请耐心等待...')


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    Main = StressMain()
    Main.show()
    sys.exit(app.exec())
